import json
import os

from httprunner import loader
from httprunner import report
from httprunner.api import HttpRunner
from httprunner.loader.load import load_dot_env_file
from httprunner.loader.buildup import load_debugtalk_functions

from .. import settings


class HrunCall():
    """
      封装 Httprunner 的调用

      0、读取数据（excel、json or 其他）
      1、生成Testcase对象
      2、封装Hrun的对象
      3、调用Hrun测试方法
      4、输出报告
    """

    def __init__(self) -> None:
        super().__init__()
        self.testcaseObj = None

        self.workDir = settings.workDir

    def _hrun_run_tests(self, oHrun, testcontent):
        # 自行封装 hrun， 忽略json校验

        project_working_directory = testcontent.get("project_mapping", {}).get("PWD", os.getcwd())
        loader.init_pwd(project_working_directory)
        return oHrun.run_tests(testcontent)

    def _hrun_run(self):

        runner = HttpRunner(failfast=False, save_tests=True, log_level=settings.log_level)
        #     log_file="test.log"
        # )

        testcontent = self._genHttpRunner()
        print(testcontent)
        # print(json.dumps(testcontent, indent=4, separators=(',', ':'), ensure_ascii=False))

        if 'testsuites' in testcontent:
            # 判断是否包含 testsuites
            return self._hrun_run_tests(runner, testcontent)
        else:
            return runner.run(testcontent)

    def callHrun(self, tcname=''):

        # 运行单个结构体
        summary = self._hrun_run()
        # summary = runner.run(tcStructure) if 'testsuites' not in tcStructure else \
        #     self._hrun_run_tests(runner, tcStructure)

        # print(summary)

        # 输出测试报告
        HrunReport(tcname).genReport(summary)


    def _loadenv(self):
        # load .env file
        # NOTICE:
        # environment variable maybe loaded in debugtalk.py
        # thus .env file should be loaded before loading debugtalk.py
        dot_env_path = os.path.join(self.workDir, ".env")
        if not os.path.isfile(dot_env_path):
            dot_env_path = os.path.join(self.workDir, "testcases/.env")
            if not os.path.isfile(dot_env_path):
                return {}

        xenv = load_dot_env_file(dot_env_path)
        print(xenv)
        return xenv

    def _genHttpRunner(self):
        modeName = 'testsuites' if 'testcases' in self.testcaseObj[0] else 'testcases'

        return {"project_mapping": {
                    "PWD": self.workDir,
                    "functions": load_debugtalk_functions(),
                    "env": self._loadenv()
                },
                modeName: self.testcaseObj
            }

    # todo 使用 testsuite模式执行
    """
            tests_mapping (dict): project info and testcases list.

            {
                "project_mapping": {
                    "PWD": "XXXXX",
                    "functions": {},
                    "variables": {},                        # optional, priority 1
                    "env": {}
                },
                "testsuites": [
                    {   # testsuite data structure
                        "config": {},
                        "testcases": {
                            "testcase1 name": {
                                "variables": {
                                    "uid": 1000
                                },
                                "parameters": {
                                    "uid": [100, 101, 102]
                                },
                                "testcase_def": {
                                    "config": {},
                                    "teststeps": []
                                }
                            },
                            "testcase2 name": {}
                        }
                    }
                ],
                "testcases": [
                    {   # testcase data structure
                        "config": {
                            "name": "desc1",
                            "path": "testcase1_path",
                            "variables": {},                # optional, priority 2
                        },
                        "teststeps": [
                            # test data structure
                            {
                                'name': 'test step desc1',
                                'variables': [],            # optional, priority 3
                                'extract': [],
                                'validate': [],
                                'api_def': {
                                    "variables": {}         # optional, priority 4
                                    'request': {},
                                }
                            },
                            test_dict_2   # another test dict
                        ]
                    },
                    testcase_dict_2     # another testcase dict
                ],
                "api": {
                    "variables": {},
                    "request": {}
                }
            }
            """


class HrunReport:
    """
    测试报告封装
    """
    def __init__(self, tcname):
        self.workDir = settings.workDir
        self.tcname = tcname

    def genReport(self, summary ):

        report_template = self.get_reportTemplate()

        # 测试报告路径
        reportDir = self.get_reportDir(self.tcname if not self.tcname == '' else summary['details'][0]['name'])
        if report_template == '':
            report_path = report.gen_html_report(
                summary,
                # report_template=os.path.join(self.workDir, 'hruntools/report/extent-theme-template.html'),
                report_dir=reportDir
                # report_file="/path/to/report_file_path"
            )

        else:
            # 指定报告模版
            report_path = report.gen_html_report(
                summary,
                report_template=report_template,
                report_dir=reportDir
                # report_file="/path/to/report_file_path"
            )
        self.show_reportURL(settings.report_url, report_path)

    def get_reportTemplate(self):
        if settings.extend_report_type:
            return os.path.join(settings.rootPath, settings.ReportTemplate)
        else:
            return os.path.join(settings.rootPath, settings.ReportTemplatex)

    def get_reportDir(self, tcname):
        return os.path.join(self.workDir, 'reports/' + tcname)

    def show_reportURL(self, url, path):
        if url != '':
            from urllib import parse
            if url.endswith("/"):  # 去除url尾部 /
                url = url[:-1]

            print("\nReport file URL = %s" % (
                parse.urljoin(url, parse.quote('/'.join(path.replace('\\', '/').split('/')[-3:])))))


def load_debugtalk_functions1():
    """ load project debugtalk.py module functions
        debugtalk.py should be located in project working directory.

    Returns:
        dict: debugtalk module functions mapping
            {
                "func1_name": func1,
                "func2_name": func2
            }

    """
    # load debugtalk.py module
    import importlib
    imported_module = importlib.import_module("debugtalk")
    from httprunner.loader.load import load_module_functions
    return load_module_functions(imported_module)
